/*
 * Created on Jan 1, 2005
 *
 */
package com.xhrd.generator.provider.db.table.model;


import java.util.List;

import com.xhrd.generator.provider.db.table.TableFactory;
import com.xhrd.generator.util.ListHashtable;
import com.xhrd.generator.util.StringHelper;


/**
 * @author chris
 *
 */
public class ForeignKey {


    protected String   relationShip   = null;
    protected String   firstRelation  = null;
    protected String   secondRelation = null;
    protected Table parentTable ;
    protected String   tableName;
    protected ListHashtable columns ;
    protected ListHashtable parentColumns;

    public ForeignKey(Table aTable, String tblName) {
        super();
        parentTable = aTable;
        tableName   = tblName;
        columns = new ListHashtable();
        parentColumns = new ListHashtable();
    }

    /**
     * @return Returns the tableName.
     */
    public String getTableName() {
        return tableName;
    }
    public String getParentTableName() {
        return parentTable.getSqlName();
    }
    /**
     * @param col
     * @param seq
     */
    public void addColumn(String col,  String parentCol, Integer seq) {
        columns.put(seq, col);
        parentColumns.put(seq,parentCol);
    }
    public String getColumn(String parentCol) {
        // return the associated column given the parent column
        Object key = parentColumns.getKeyForValue(parentCol);
        String col = (String) columns.get(key);
        //System.out.println("get Column for" +parentCol);
        //System.out.println("key = "+key);
        //System.out.println("col="+col);
        //System.out.println("ParentColumns = "+parentColumns.toString());
        return col;
    }
    public ListHashtable getColumns() {
        return columns;
    }
    /**
     *
     */
    private void initRelationship() {
        firstRelation   = "";
        secondRelation  = "";
        Table foreignTable = null;
        try {
            foreignTable = (Table) TableFactory.getInstance().getTable(tableName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List parentPrimaryKeys    = parentTable.getPrimaryKeyColumns();
        List foreignPrimaryKeys   = foreignTable.getPrimaryKeyColumns();

        if (hasAllPrimaryKeys(parentPrimaryKeys,parentColumns))
            firstRelation = "one";
        else
            firstRelation = "many";

        if (hasAllPrimaryKeys(foreignPrimaryKeys,columns))
            secondRelation = "one";
        else
            secondRelation = "many";

        relationShip = firstRelation + "-to-" + secondRelation;

    }
    private boolean hasAllPrimaryKeys(List pkeys, ListHashtable cols) {
        boolean hasAll = true;
        // if size is not equal then false
        int numKeys = pkeys.size();
        if (numKeys != cols.size())
            return false;

        for (int i=0;i<numKeys;i++) {
            Column col = (Column) pkeys.get(i);
            String colname = col.getColumnName();
            if (!cols.contains(colname))
                return false;
        }

        return hasAll;
    }
    public boolean isParentColumnsFromPrimaryKey() {
        boolean isFrom = true;
        List keys = parentTable.getPrimaryKeyColumns();
        int numKeys = getParentColumns().size();
        for (int i=0;i<numKeys;i++) {
            String pcol = (String) getParentColumns().getOrderedValue(i);
            if (!primaryKeyHasColumn(pcol)) {
                isFrom=false;
                break;
            }
        }
        return  isFrom;
    }
    private boolean primaryKeyHasColumn(String aColumn) {
        boolean isFound = false;
        int numKeys = parentTable.getPrimaryKeyColumns().size();
        for (int i=0;i<numKeys;i++) {
            Column sqlCol = (Column)parentTable.getPrimaryKeyColumns().get(i);
            String colname = sqlCol.getColumnName();
            if (colname.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return isFound;
    }
    public boolean getHasImportedKeyColumn(String aColumn) {
        boolean isFound = false;
        List cols = getColumns().getOrderedValues();
        int numCols = cols.size();
        for (int i=0;i<numCols;i++) {
            String col = (String) cols.get(i);
            if (col.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return  isFound;
    }
    /**
     * @return Returns the firstRelation.
     */
    public String getFirstRelation() {
        if (firstRelation == null)
            initRelationship();
        return firstRelation;
    }
    public Table getSqlTable() {
        Table table = null;
        try {
            table = (Table) TableFactory.getInstance().getTable(tableName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }
    /**
     * @return Returns the parentTable.
     */
    public Table getParentTable() {
        return parentTable;
    }
    /**
     * @return Returns the relationShip.
     */
    public String getRelationShip() {
        if (relationShip == null)
            initRelationship();
        return relationShip;
    }
    /**
     * @return Returns the secondRelation.
     */
    public String getSecondRelation() {
        if (secondRelation == null)
            initRelationship();
        return secondRelation;
    }
    /**
     * @return Returns the parentColumns.
     */
    public ListHashtable getParentColumns() {
        return parentColumns;
    }

    public boolean getHasImportedKeyParentColumn(String aColumn) {

        boolean isFound = false;
        List cols = getParentColumns().getOrderedValues();
        int numCols = cols.size();
        for (int i=0;i<numCols;i++) {
            String col = (String) cols.get(i);
            if (col.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return  isFound;
    }

    /**
     * 外键引用使用的值对象
     * @author badqiu
     *
     */
    public static class ReferenceKey {
        public String schemaName;
        public String tableName;
        public String columnSqlName;
        public ReferenceKey(String schemaName, String tableName,String columnSqlName) {
            this.schemaName = StringHelper.defaultIfEmpty(schemaName, null);
            this.tableName = tableName;
            this.columnSqlName = columnSqlName;
        }

        public String toString() {
            if(StringHelper.isBlank(schemaName)) {
                return tableName+"("+columnSqlName+")";
            }else {
                return schemaName+"."+tableName+"("+columnSqlName+")";
            }
        }

        public static String toString(ReferenceKey k) {
            if(k == null) return null;
            return k.toString();
        }

        /**
         * 解析foreignKey字符串,格式: fk_table_name(fk_column) 或者 schema_name.fk_table_name(fk_column)
         * @param foreignKey
         * @return
         */
        public static ReferenceKey fromString(String foreignKey) {
            if(StringHelper.isBlank(foreignKey)) {
                return null;
            }
            if(!foreignKey.trim().matches(".*\\w+\\(.*\\)")) {
                throw new IllegalArgumentException("Illegal foreignKey:["+foreignKey+"] ,example value: fk_table_name(fk_column) ");
            }
            String schemaName = foreignKey.substring(0,Math.max(foreignKey.lastIndexOf("."),0));
            String tableSqlName = foreignKey.substring(Math.max(foreignKey.lastIndexOf(".")+1,0),foreignKey.indexOf("("));
            String columnSqlName = foreignKey.substring(foreignKey.indexOf("(")+1,foreignKey.indexOf(")"));
            return new ReferenceKey(schemaName,tableSqlName,columnSqlName);
        }
    }
}
